
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>G4F DEMO</title>
    <link rel="apple-touch-icon" sizes="180x180" href="dist/img/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="dist/img/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="dist/img/favicon-16x16.png">
    <link rel="manifest" href="dist/img/site.webmanifest">
    <style>
        :root {
            --colour-1: #000000;
            --colour-2: #ccc;
            --colour-3: #e4d4ff;
            --colour-4: #f0f0f0;
            --colour-5: #181818;
            --colour-6: #242424;
            --accent: #8b3dff;
            --gradient: #1a1a1a;
            --background: #16101b;
            --size: 70vw;
            --top: 50%;
            --blur: 40px;
            --opacity: 0.6;
        }

        .gradient {
            position: absolute;
            left: 50vw;
            border-radius: 50%;
            background: radial-gradient(circle at center, var(--accent), var(--gradient));
            width: var(--size);
            height: var(--size);
            top: var(--top);
            transform: translate(-50%, -50%);
            filter: blur(var(--blur)) opacity(var(--opacity));
            animation: zoom_gradient 6s infinite alternate;
            display: none;
            max-height: 100%;
            transition: max-height 0.25s ease-in;
        }

        .gradient.hidden {
            max-height: 0;
            transition: max-height 0.15s ease-out;
        }

        @media only screen and (min-width: 40em) {
            body .gradient{
                display: block;
            }
        }

        /* Animation for the gradient circle */
        @keyframes zoom_gradient {
            0% {
                transform: translate(-50%, -50%) scale(1);
            }
            100% {
                transform: translate(-50%, -50%) scale(1.5);
            }
        }

        /* Body and text color */
        body {
            background: var(--background);
            height: 100vh;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        .hidden {
            display: none;
        }

        #background, #image-feed, #video-feed {
            height: 100%;
            position: absolute;
            object-fit: cover;
            object-position: center;
            width: 100%;
            background: black;
        }
    </style>
    <link rel="stylesheet" href="dist/css/all.min.css">
    <script src="dist/js/framework.js"></script>
</head>
<body>
    <img id="image-feed" class="hidden" alt="Image Feed">
    <video id="video-feed" class="hidden" alt="Video Feed" autoplay muted></video>
    <video id="preload" class="hidden" alt="" autoplay muted></video>

    <!-- Gradient Background Circle -->
    <div class="gradient"></div>
    <script>
        (async () => {
            const videoUrl = "/search/video?skip=";
            const url = "https://image.pollinations.ai/feed";
            const imageFeed = document.getElementById("image-feed");
            const videoFeed = document.getElementById("video-feed");
            const preload = document.getElementById("preload");
            const gradient = document.querySelector(".gradient");
            const images = [];
            let es = null;
            let skipVideo = 2;
            let skipImage = 0;
            let errorVideo = 0;
            let errorImage = 0;
            let skipRefresh = 0;
            videoFeed.onloadeddata = () => {
                videoFeed.classList.remove("hidden");
                gradient.classList.add("hidden");
            };
            videoFeed.onerror = (e) => {
                videoFeed.classList.add("hidden");
                errorVideo += 1;
                if (errorVideo > 3) {
                    gradient.classList.remove("hidden");
                    return;
                }
                videoFeed.src = window.backendUrl + videoUrl + skipVideo;
                skipVideo++;
            };
            videoFeed.onended = () => {
                videoFeed.src = window.backendUrl + videoUrl + skipVideo;
                preload.src = window.backendUrl + videoUrl + (skipVideo + 1);
                skipVideo++;
            };
            videoFeed.onclick = () => {
                videoFeed.src = window.backendUrl + videoUrl + skipVideo;
                skipVideo++;
            };
            videoFeed.src = window.backendUrl + videoUrl + skipVideo;
            preload.src = window.backendUrl + videoUrl + (skipVideo + 1);
            function initES() {
                if (es == null || es.readyState == EventSource.CLOSED) {
                    const eventSource = new EventSource(url);
                    eventSource.onmessage = (event) => {
                        const data = JSON.parse(event.data);
                        if (data.nsfw || !data.nologo || data.width < 512 || !data.imageURL || data.isChild || data.status != "end_generating") {
                            return;
                        }
                        const lower = data.prompt.toLowerCase();
                        const tags = ["nsfw", "timeline", "feet", "blood", "soap", "orally", "heel", "latex", "bathroom", "boobs", "charts", "gel", "logo", "infographic", "warts", " bra ", "prostitute", "curvy", "breasts", "written", "bodies", "naked", "classroom", "malone", "dirty", "shoes", "shower", "banner", "fat", "nipples", "couple", "sexual", "sandal", "supplier", "overlord", "succubus", "platinum", "cracy", "crazy", "hemale", "oprah", "lamic", "ropes", "cables", "wires", "dirty", "messy", "cluttered", "chaotic", "disorganized", "disorderly", "untidy", "unorganized", "unorderly", "unsystematic", "disarranged", "disarrayed", "disheveled", "disordered", "jumbled", "muddled", "scattered", "shambolic", "sloppy", "unkept", "unruly", "bottomless", "18 year"];
                        for (i in tags) {
                            if (lower.indexOf(tags[i]) != -1) {
                                console.log("Skipping image with tag: " + tags[i]);
                                console.debug("Skipping image:", data.imageURL);
                                return;
                            }
                        }
                        const landscape = window.innerWidth > window.innerHeight;
                        if (landscape && data.width > data.height) {
                            images.push(data.imageURL);
                        } else if (!landscape && data.width < data.height) {
                            images.push(data.imageURL);
                        }
                    };
                    eventSource.onerror = (event) => {
                        eventSource.close();
                    }
                }
            }
            let refreshOnHide = true;
            document.addEventListener("visibilitychange", () => {
                if (document.hidden) {
                    refreshOnHide = false;
                } else {
                    refreshOnHide = true;
                }
            });
            setInterval(() => {
                if (errorVideo < 3 || !refreshOnHide) {
                    return;
                }
                if (skipRefresh > 0) {
                    skipRefresh -= 1;
                    return;
                }
                if (errorImage < 3) {
                    imageFeed.src = window.backendUrl + "/search/image+g4f?skip=" + skipImage;
                    skipImage++;
                    return;
                }
                if (images.length > 0) {
                    imageFeed.classList.remove("hidden");
                    imageFeed.src = images.shift();
                    gradient.classList.add("hidden");
                } else {
                    initES();
                }
            }, 7000);
            imageFeed.onerror = () => {
                imageFeed.classList.add("hidden");
                gradient.classList.remove("hidden");
                errorImage++;
            };
            imageFeed.onload = () => {
                imageFeed.classList.remove("hidden");
                gradient.classList.add("hidden");
                errorImage--;
            };
            imageFeed.onclick = () => {
                imageFeed.src = window.backendUrl + "/search/image?random=" + Math.random();
                if (skipRefresh < 4) {
                    skipRefresh += 1;
                }
            };
        })();
    </script>
</body>
</html>